package com.qianfeng.chinatelcom.apigateway.filters;

//
//                            _ooOoo_  
//                           o8888888o  
//                           88" . "88  
//                           (| -_- |)  
//                            O\ = /O  
//                        ____/`---'\____  
//                      .   ' \\| |// `.  
//                       / \\||| : |||// \  
//                     / _||||| -:- |||||- \  
//                       | | \\\ - /// | |  
//                     | \_| ''\---/'' | |  
//                      \ .-\__ `-` ___/-. /  
//                   ___`. .' /--.--\ `. . __  
//                ."" '< `.___\_<|>_/___.' >'"".  
//               | | : `- \`.;`\ _ /`;.`/ - ` : | |  
//                 \ \ `-. \_ __\ /__ _/ .-` / /  
//         ======`-.____`-.___\_____/___.-`____.-'======  
//                            `=---='  
//  
//         .............................................  
//                  佛祖镇楼                  BUG辟易  
//          佛曰:  
//                  写字楼里写字间，写字间里程序员；  
//                  程序人员写程序，又拿程序换酒钱。  
//                  酒醒只在网上坐，酒醉还来网下眠；  
//                  酒醉酒醒日复日，网上网下年复年。  
//                  但愿老死电脑间，不愿鞠躬老板前；  
//                  奔驰宝马贵者趣，公交自行程序员。  
//                  别人笑我忒疯癫，我笑自己命太贱；  
//  


import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import com.qianfeng.chinatelcom.apigateway.cache.GrayReleaseLocalCache;
import io.jmnarloch.spring.cloud.ribbon.support.RibbonFilterContextHolder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;

import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * Created by Jackiechan on 2021/12/3/上午9:46
 *
 * @author Jackiechan
 * @version 1.0
 * @since 1.0
 */
@Component
public class GrayReleaseFilter extends ZuulFilter {

    private GrayReleaseLocalCache grayReleaseLocalCache;

    @Autowired
    public void setGrayReleaseLocalCache(GrayReleaseLocalCache grayReleaseLocalCache) {
        this.grayReleaseLocalCache = grayReleaseLocalCache;
    }

    @Override
    public String filterType() {
        return FilterConstants.PRE_TYPE;
    }

    @Override
    public int filterOrder() {
        return FilterConstants.PRE_DECORATION_FILTER_ORDER + 1000;
    }

    @Override
    public boolean shouldFilter() {
        RequestContext context = RequestContext.getCurrentContext();
        boolean lanjie = context.sendZuulResponse();
        Object service = context.get(FilterConstants.SERVICE_ID_KEY);//获取到要转发的服务的名字
//        Object url = context.get(FilterConstants.REQUEST_URI_KEY);//要转发的地址
        Object url = context.get("yuanshidizhi");//要转发的地址,这里取原始地址的原因是因为我们灰度发布中匹配的是参数化的路径，并不是真实的访问路径，所以我们在这里要执行原始的地址
        //当前访问的地址处于灰度发布列表中才可以执行这个过滤器
        List<Map> config = grayReleaseLocalCache.getGrayConfig(service + "" + url);
        if (config == null || config.size() == 0) {
            //没有规则就直接返回false
            return false;
        }
        context.put("grayguize", config);//保存规则，目的是在下面的run中可以快速使用
        context.put("path", service + "" + url);//保存请求的路径
        return lanjie;
    }

    @Override
    public Object run() throws ZuulException {
        System.err.println("灰度规则开始执行了");
        RequestContext context = RequestContext.getCurrentContext();
        //根据地址获取到已经在使用的是规则， 比如还剩多少个1 2 3等标识
        String path = context.get("path") + "";//正在访问的路径
        List<String> pathConfig = grayReleaseLocalCache.getUsedConfig(path);//根据路径获取到正在使用的规则
        //如果没有了就重新放进去一次
        if (pathConfig == null || pathConfig.size() == 0) {
            List<Map> grayguize = (List<Map>) context.get("grayguize");
            grayguize.forEach(map -> {
                Integer percent = (Integer) map.get("percent");//获取到次数
                String forward = (String) map.get("forward");//服务的标识
                for (Integer i = 0; i < percent; i++) {
                    grayReleaseLocalCache.add2Config(path,forward);//保存规则
                }

            });
        }
        pathConfig = grayReleaseLocalCache.getUsedConfig(path);//重新获取一次规则
        System.err.println(pathConfig);
        Collections.shuffle(pathConfig);
        String forwardvalue = pathConfig.remove(0);//我们总是移除下标为0的数据,获取到要访问的服务的标识
        //
        //我现在想要按照流量切换，你访问哪个版本都可以获取到数据，但是有个新版本内部发生了变化，我想要慢慢的切换到新版本
        //我們需要在某个地方保存着需要灰度的接口的配置，比如什么标识多少比例或者多少次
        //我们现在期望10左右的流量切换到新版本，70还在之前
        RibbonFilterContextHolder.getCurrentContext().add("forward", forwardvalue);//添加要访问的服务的标识，定义在metadata-map中,实现灰度发布
        return null;
    }
}
